﻿using Corina.Commands;
using Corina.Enumerations;
using Corina.Infrastructure;
using Corina.Lantern.DataService;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
using System.Reflection;
using System.ServiceModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq;

namespace Corina.Lantern.Hub.Viewmodels
{
    public class ViewmodelBase : BaseClass
    {
        protected DataContainer DataContext
        {
            get
            {
                if (!IsDesignMode)
                {
                    //return (DataContainer)((MainPage)App.Current.RootVisual).DataContext;
                    MainPage main = (MainPage)Application.Current.RootVisual;
                    return (DataContainer)main.DataContext;
                }
                else
                {
                    return new DataContainer();
                }
            }
        }

        public string WebServiceAddress
        {
            get
            {
                if (Application.Current.IsRunningOutOfBrowser || IsDesignMode)
                {
                    return "http://www.byshuju.cn/";
                }
                
                return Application.Current.Resources["WebServiceAddress"] as string;
            }
        }

        #region Soap Clients
        protected CoreSoapClient CoreClient { get; set; }
        protected DeviceSoapClient DeviceClient { get; set; }
        protected MeasureSoapClient MeasureClient { get; set; }
        protected UserSoapClient UserClient { get; set; }
        protected CommonSoapClient CommonClient { get; set; }
        protected ThirdPartyMeasureSoapClient ThirdMeasureClient { get; set; }
        protected DatasSoapClient DatasClient { get; set; }
        #endregion

        #region Constructor
        public ViewmodelBase()
        {
            CoreClient = new CoreSoapClient(WebBindingConfig.HttpBinding, new EndpointAddress(WebServiceAddress + ConstUrls.URL_CORE));
            DeviceClient = new DeviceSoapClient(WebBindingConfig.HttpBinding, new EndpointAddress(WebServiceAddress + ConstUrls.URL_DEVICE));
            MeasureClient = new MeasureSoapClient(WebBindingConfig.HttpBinding, new EndpointAddress(WebServiceAddress + ConstUrls.URL_DEVICEMEASURE));
            UserClient = new UserSoapClient(WebBindingConfig.HttpBinding, new EndpointAddress(WebServiceAddress + ConstUrls.URL_USER));
            CommonClient = new CommonSoapClient(WebBindingConfig.HttpBinding, new EndpointAddress(WebServiceAddress + ConstUrls.URL_COMMONBASE));
            ThirdMeasureClient = new ThirdPartyMeasureSoapClient(WebBindingConfig.HttpBinding, new EndpointAddress(WebServiceAddress + ConstUrls.URL_THIRDPARTY));
            DatasClient = new DatasSoapClient(WebBindingConfig.HttpBinding, new EndpointAddress(WebServiceAddress + ConstUrls.URL_DATAS));
        }
        #endregion

        #region Common Properties
        protected bool IsDesignMode
        {
            get
            {
                return DesignerProperties.IsInDesignTool;//(bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(FrameworkElement)).Metadata.DefaultValue;
            }
        }

        private bool _isbusy = false;
        public virtual bool IsBusy
        {
            get { return _isbusy; }
            set
            {
                _isbusy = value;
                RaisePropertyChanged(() => IsBusy);
            }
        }

        private EntityOperation _operation = EntityOperation.None;
        public EntityOperation Operation
        {
            get { return _operation; }
            set
            {
                _operation = value;
                RaisePropertyChanged(() => Operation);
                OperationChanged();
            }
        }

        public virtual bool ShowUpdate
        {
            get { return Operation != EntityOperation.None; }
        }
        #endregion

        #region Virtual Methods
        protected virtual void LoadData(params object[] paras)
        { }

        protected virtual void OperationChanged()
        {
            RaisePropertyChanged(() => ShowUpdate);
        }

        protected virtual void CurrentIndexChanged()
        {
            LoadData();
        }

        protected virtual object GetObjectPropertyValue(object obj, string name)
        {
            Type t = obj.GetType();
            PropertyInfo p = t.GetProperty(name);
            object v = p.GetValue(obj, null);
            return v;
        }

        protected virtual string GetOperateResult(ResultValue result)
        {
            string key = "IDS_OPERATE_RESULT_" + result.ToString().ToUpper();
            if (Application.Current.Resources.Contains(key))
            {
                return (string)Application.Current.Resources[key];
            }
            else
            {
                return result.ToString();
            }
        }

        protected virtual IEnumerable<DependencyObject> GetChildrenRecursively(DependencyObject root)
        {
            List<DependencyObject> children = new List<DependencyObject>();
            children.Add(root);
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
                children.AddRange(GetChildrenRecursively(VisualTreeHelper.GetChild(root, i)));

            return children;
        }

        protected virtual DependencyObject FindControl(DependencyObject root, string name)
        {
            IEnumerable<DependencyObject> objs = GetChildrenRecursively(root);
            
            return objs.FirstOrDefault(t => (t as Control).Name == name);
        }

        protected virtual T FindControl<T>(DependencyObject root, string name) where T : FrameworkElement
        {
            IEnumerable<T> objs = GetChildrenRecursively(root).OfType<T>();
            return (T)objs.FirstOrDefault(t => t.Name == name);
        }

        #endregion

        #region Current Account
        protected string Account
        {
            get
            {
                return DataContext.IsValid ? DataContext.CurrentAccount.Account : string.Empty;
            }
        }

        protected string Password
        {
            get
            {
                return DataContext.IsValid ? DataContext.CurrentAccount.Password : string.Empty;
            }
        }
        #endregion

        #region Pagination
        private int _index = 1;
        public int Index
        {
            get { return _index; }
            set
            {
                _index = value;
                RaisePropertyChanged(() => Index);
                CurrentIndexChanged();
                RaisePropertyChanged(() => FirstPageCommand);
                RaisePropertyChanged(() => PreviousPageCommand);
                RaisePropertyChanged(() => NextPageCommand);
                RaisePropertyChanged(() => LastPageCommand);
            }
        }

        private int _itemsCount = 0;
        public int ItemsCount
        {
            get { return _itemsCount; }
            set
            {
                _itemsCount = value;
                RaisePropertyChanged(() => ItemsCount);
                RaisePropertyChanged(() => PagesCount);
                RaisePropertyChanged(() => FirstPageCommand);
                RaisePropertyChanged(() => PreviousPageCommand);
                RaisePropertyChanged(() => NextPageCommand);
                RaisePropertyChanged(() => LastPageCommand);
            }
        }

        public int PagesCount
        {
            get
            {
                return ItemsCount > 0 ? ((ItemsCount + 19) / 20) : 1;
            }
        }

        public ICommand FirstPageCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return Index > 1; },
                    ExecuteCallback = delegate
                    {
                        Index = 1;
                    }
                };
            }
        }

        public ICommand PreviousPageCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return Index > 1; },
                    ExecuteCallback = delegate
                    {
                        Index--;
                    }
                };
            }
        }

        public ICommand NextPageCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return Index < PagesCount; },
                    ExecuteCallback = delegate
                    {
                        Index++;
                    }
                };
            }
        }

        public ICommand LastPageCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return Index < PagesCount; },
                    ExecuteCallback = delegate
                    {
                        Index = PagesCount;
                    }
                };
            }
        }
        #endregion
    }
}
